package infra

import (
	"errors"
	"fmt"
	"time"

	"github.com/go-resty/resty/v2"
	"github.com/sirupsen/logrus"
	"github.com/xuelang-group/sh-solver-scheduler/internal/domain/entity"
)

const (
	solverTaskManagerEndpoint = "http://sh-dc-resource-manager.sh-dc:8080"
)

type RespGetNewSolverTaskId struct {
	Success bool   `json:"success"`
	Message string `json:"message"`
	Data    int    `json:"data"`
}

func GetNewSolverTaskId(taskName string, status string, solverId string, resourceCPU uint, resourceMEM uint, resultAddr string, spec string) (int, error) {
	result := RespGetNewSolverTaskId{}

	client := resty.New()
	resp, err := client.R().
		SetHeader("Content-Type", "application/json").
		SetHeader("Accept", "application/json").
		SetBody(map[string]interface{}{
			"name":        taskName, // 任务名称
			"status":      status,   // 任务状态
			"solverId":    solverId, // 求解器id
			"resourceCPU": resourceCPU,
			"resourceMEM": resourceMEM,
			"resultAddr":  resultAddr, // 结果保存地址
			"spec":        spec,       // 求解元信息
		}).
		SetResult(&result).
		Post(solverTaskManagerEndpoint + "/taskSolver/save")
	if err != nil {
		logrus.Error(err)
		return 0, err
	}

	if !resp.IsSuccess() {
		err := errors.New("get solver task id failed")
		logrus.Error(err)
		return 0, err
	}

	return result.Data, nil
}

type RespSolverSpec struct {
	Success bool              `json:"success"`
	Code    int               `json:"code"`
	Message string            `json:"message"`
	Data    entity.SolverSpec `json:"data"`
}

// 获取求解器定义
func GetSolverSpec(solverId string) (entity.SolverSpec, error) {
	result := RespSolverSpec{}

	client := resty.New()
	resp, err := client.R().
		SetHeader("Content-Type", "application/json").
		SetHeader("Accept", "application/json").
		SetResult(&result).
		Get(solverTaskManagerEndpoint + fmt.Sprintf("/solver/%v", solverId))
	if err != nil {
		logrus.Error(err)
		return result.Data, err
	}

	if !resp.IsSuccess() || !result.Success {
		err := errors.New("get solver spec failed")
		logrus.Error(err)
		return result.Data, err
	}

	return result.Data, nil
}

type RespUpdateSolverTaskStatus struct {
	Success bool   `json:"success"`
	Code    int    `json:"code"`
	Message string `json:"message"`
}

func UpdateSolverTaskStatus(solverTaskId int, status string) (bool, error) {
	result := RespUpdateSolverTaskStatus{}

	client := resty.New()
	resp, err := client.R().
		SetHeader("Content-Type", "application/json").
		SetHeader("Accept", "application/json").
		SetBody(map[string]interface{}{
			"taskId": solverTaskId,
			"status": status,
			"time":   time.Now().Format("2006-01-02 15:04:05"),
		}).
		SetResult(&result).
		Post(solverTaskManagerEndpoint + "/taskSolver/status")
	if err != nil {
		logrus.Error(err)
		return false, err
	}

	logrus.Debugf("updateSolverTaskStatus, result: %+v", result)

	if !resp.IsSuccess() || !result.Success {
		err := errors.New("update solver task status failed")
		logrus.Error(err)
		return false, err
	}

	return true, nil
}

type RespUpdateSolverTaskLogMsg struct {
	Success bool   `json:"success"`
	Code    int    `json:"code"`
	Message string `json:"message"`
}

func UpdateSolverTaskLogMsg(solverTaskId int, logMsg string, reqType string) (bool, error) {
	result := RespUpdateSolverTaskLogMsg{}

	client := resty.New()
	resp, err := client.R().
		SetHeader("Content-Type", "application/json").
		SetHeader("Accept", "application/json").
		SetBody(map[string]interface{}{
			"taskId": solverTaskId,
			"logMsg": logMsg,
			"type":   reqType, // override覆盖 append追加
		}).
		SetResult(&result).
		Post(solverTaskManagerEndpoint + "/taskSolver/log")
	if err != nil {
		logrus.Error(err)
		return false, err
	}

	if !resp.IsSuccess() || !result.Success {
		err := errors.New("update solver task logmsg failed")
		logrus.Error(err)
		return false, err
	}

	return true, nil
}
